package warehouse;

import gudusoft.gsqlparser.EDbVendor;
import gudusoft.gsqlparser.TCustomSqlStatement;
import gudusoft.gsqlparser.TGSqlParser;
import gudusoft.gsqlparser.nodes.TResultColumn;
import gudusoft.gsqlparser.nodes.TResultColumnList;
import gudusoft.gsqlparser.nodes.TTable;
import java.io.BufferedReader;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 *
 * @author Manolescu Razvan
 */
public class Util {

    public static String join(String[] strings) {
        return join(strings, ",");
    }

    public static String join(String[] strings, String delimiter) {
        if (strings == null || strings.length == 0) {
            return null;
        }
        StringBuilder sb = new StringBuilder(strings[0]);

        for (int i = 1; i < strings.length; i++) {
            sb.append(delimiter);
            sb.append(strings[i]);
        }

        return sb.toString();
    }
    
    public enum DBDataType{
        INT("int", 4),
        TINYINT("tinyint", 1),
        BIGINT("bigint", 8),
        VARCHAR("varchar", 1),
        DATE("date", 3);
        
        private int sizeInB;
        private String name;
        DBDataType(final String name, final int size){
            this.sizeInB = size;
            this.name = name;
        }
       
        public static int getVarcharSize(int length){
            if(length > 255){
                return length + 2;
            }
            else{
                return length + 1;
            }
        }

        public String getName() {
            return name;
        }

        public int getSizeInB() {
            return sizeInB;
        }
        
        public static DBDataType fromStringFuzzy(final String value){
            for(DBDataType dataType : values()){
                if(value.contains(dataType.getName())){
                    return dataType;
                }
            }
            
            return null;
        }
        
        public static int getLengthFromDB(final String value){
            if(value.contains("varchar")){
                String len = value.split("\\(")[1].split("\\)")[0];
                return Integer.valueOf(len);
            }
            return 1;
        }
    }
    
    public enum ParseType {
        TABLE, COLUMN;
    }
    
    public static Map<String, List<String>> parseQuery(final String query)
    {
        final Map<String, List<String>> retMap = new HashMap<String, List<String>>();
        final TGSqlParser sqlParser = new TGSqlParser(EDbVendor.dbvmysql);
        
        sqlParser.sqltext = query;
        int ret = sqlParser.parse();
        if(ret == 0){
            for(int i=0; i<sqlParser.sqlstatements.size(); i++){
                final TCustomSqlStatement stat = sqlParser.sqlstatements.get(i);
                final TResultColumnList list = stat.getResultColumnList();
                
                for(int j=0; j<list.size(); j++){
                    final TResultColumn col = list.getResultColumn(j);

                    final String sT = col.getStartToken().toString();
                    if(retMap.get(sT) == null){
                        final List<String> colList = new ArrayList<String>();
                        retMap.put(sT, colList);
                    }
                    
                    //final TExpression texp = col.getExpr();
                    // TODO : fix this
                    final String tS = col.getEndToken().toString();
                    retMap.get(sT).add(tS);                
                }
                
                                
                for(int k=0; k<stat.tables.size(); k++){
                    final TTable t = stat.tables.getTable(k);
                    final String tableAlias = t.getAliasClause() == null ? t.getFullName() : t.getAliasClause().toString();
                    retMap.put(t.getFullName(), retMap.get(tableAlias));
                    if(t.getAliasClause() != null){
                     retMap.remove(tableAlias);
                    }
                }
            
                System.out.println("WHERE clause "+stat.getWhereClause());
            }
        }
        else{
            System.out.println("[ERROR] Statement parse error"+query);
        }
        
        return retMap;
    }
    
    private static boolean containsAll( Map<String, List<String>> colMap,  Map<String, List<String>> colMap2){
        for(String tabl1 :  colMap.keySet()){
            if(colMap2.get(tabl1) == null)
                return false;
            
            else {
                if(colMap.get(tabl1) == null)
                    return false;
                
                for(String column: colMap.get(tabl1)){
                    if( !colMap.get(tabl1).contains(column)){
                        return false;
                    }
                }
            }
        }
        
        return true;
    }
    
    final static String useDatamart(final String query, final Collection<DatamartInfo> dmInfo){
        final Map<String, List<String>> colMap = parseQuery(query);
        if(colMap == null)
            return query;
        
        DatamartInfo foundDataMart = null;
        for(DatamartInfo di : dmInfo){
            if(containsAll(colMap, di.tableColumn)){
                System.out.println("FOUND IN "+di.name);
                foundDataMart = di;
            }
        }
        
        if(foundDataMart == null)
            return query;
        
        
        final StringBuilder sb = new StringBuilder("SELECT ");
        List<String> bigList = new ArrayList<String>();
        
        for(List<String> colList : colMap.values()){
            bigList.addAll(colList);
        }
        
        for(int i=0; i<bigList.size(); i++){
            sb.append(bigList.get(i));
            if(i<bigList.size() -1 )
                sb.append(", ");
        }
        
        sb.append(" FROM ");
        sb.append(foundDataMart.name);
        
        final String whereClause = query.split("WHERE") == null ? null : query.split("WHERE")[1];
        if(whereClause != null){
            sb.append(" WHERE ");
            int i=0;
            for(String cond : whereClause.split("AND")){ System.out.println("COND '"+cond +"'");
                if(i!=0)  sb.append(" AND ");
                i++;
                if(cond.contains("id") || cond.contains("Id") || cond.contains("ID"))
                    sb.append(" TRUE ");
                else{
                    sb.append(cond);
                }
            }
            
//            i=0;
//            for(String cond : whereClause.split("OR")){
//                 if(i!=0)  sb.append(" OR ");
//                i++;
//                if(cond.contains("id") || cond.contains("Id") || cond.contains("ID"))
//                    sb.append(" TRUE ");
//                else{             
//                    sb.append(cond);
//                }
//            }
        }
        
        return sb.toString();
    }
    
    
   public static Map<String, BloomFilterColumn> createBloomFilterColumns(final Persistance p) throws Exception{
        final Map<String, BloomFilterColumn> bloomMap = new HashMap<String, BloomFilterColumn>();
        final String delimiter = "\\.";
        BufferedReader bf = new BufferedReader(new FileReader(Constants.FILE_ROOT + Constants.BLOOM_FILTERED_COLS));
        String line = null;
        while((line = bf.readLine()) != null){
            final String[] sp = line.split(delimiter);
            if(sp == null || sp.length < 2) 
                continue;
            final List<Integer> values = p.getIntValues(sp[0], sp[1]);
            
            final BloomFilterColumn bfc = new BloomFilterColumn(sp[1], values);
            bloomMap.put(sp[1], bfc);
        }
        
        return bloomMap;
    }
    
    public static void main(String[] args) throws Exception{
        final Persistance p = new Persistance();
//        
//        final String query = "SELECT shipping_company.name,shipping_comp_info.order_freq FROM shipping_comp_info,shipping_company "
//                + "WHERE shipping_comp_info.idShipping_comp_info=shipping_company.shipping_comp_info_id AND order_freq > 1000";
//        
//        final String outputQuery = useDatamart(query, p.getDatamartCache());
//        System.out.println(""+outputQuery);

//        Warehouse.indexSelectCache = p.refreshIndexSelectivity();
//        
//        Collections.sort(Warehouse.indexSelectCache);
        
        final String query =  "SELECT shipping_company.name,shipping_comp_info.order_freq FROM shipping_comp_info,shipping_company "
                + "WHERE shipping_comp_info.idShipping_comp_info=shipping_company.shipping_comp_info_id AND order_freq > 1000";
        
        System.out.println(""+query.split("(where|WHERE)")[0]);
    }
    
    
}
